using System;
using System.Collections;
using System.Collections.Specialized;
using System.Data;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using Sedna.Core.Common.Objects.Navigation;
using Spring.Expressions;

namespace Sedna.Core.Controller.Configurations
{
	/// <summary>
	/// Summary description for NameValuePairListCommandArgumentsGenerator.
	/// </summary>
	public class NameValuePairListCommandArgumentsGenerator : IDataGridCommandArgumentsGenerator
	{
		private bool escapeValues=true;

		private IList names;
		private IDictionary contextNames;
		private IDataGridCommandArgumentsGenerator next;
        private IScopePathParser scopePathParser;


	    public IScopePathParser ScopePathParser
	    {
	        set { scopePathParser = value; }
	    }

	    public bool EscapeValues
		{
			get { return escapeValues; }
			set { escapeValues = value; }
		}


		public IList Names
		{
			get { return names; }
			set { names = value; }
		}

		public IDictionary ContextNames
		{
			get { return contextNames; }
			set { contextNames = value; }
		}

		public IDataGridCommandArgumentsGenerator Next
		{
			set { next = value; }
		}

		public virtual string GenerateCommandArguments(IDataGridColumnConfiguration columnConfiguration, DataGridItem dataGridItem, IExecutionContext executionContext)
		{

			string result = string.Empty;

            NameValueCollection nvCol = dataGridItem.DataItem as NameValueCollection;
			if(nvCol != null)
			{
				result += BuildArguments(columnConfiguration.DataField, nvCol);
			}
			else
			{
                DataRowView drv = dataGridItem.DataItem as DataRowView;
				if(drv != null)
				{
					result += BuildArguments(columnConfiguration.DataField, drv);
				}
				else
				{
                    if (dataGridItem.DataItem != null)
					{
                        result += BuildArguments(columnConfiguration.DataField, dataGridItem.DataItem);
					}
				}
			}


			result += BuildArguments(executionContext);

			if(next != null)
                result += next.GenerateCommandArguments(columnConfiguration, dataGridItem, executionContext);
			
			return result;
		}


		public string BuildArguments(string dataField, DataRowView drv)
		{

			if(names == null || names.Count == 0)
			{
				if(dataField == null || dataField == string.Empty)
				{
					return string.Empty;
				}
				else
				{
					if(!drv.Row.Table.Columns.Contains(dataField))
					{
						return string.Empty;
					}
					return dataField + "=" + Escape(drv[dataField]!=null?drv[dataField].ToString():string.Empty) + ";";
				}
			}

			string result = "";

			foreach(string name in names)
			{
				if(!drv.Row.Table.Columns.Contains(name))
				{
					continue;
				}
				result += String.Format("{0}={1};", name, Escape(drv[name]!=null?drv[name].ToString():string.Empty));
			}

			return result;
		}

		public string BuildArguments(string dataField, NameValueCollection nvCol)
		{

			if(names == null || names.Count == 0)
			{
				if(dataField == null || dataField == string.Empty)
				{
					return string.Empty;
				}
				else
				{
					return dataField + "=" + Escape(nvCol[dataField]!=null?nvCol[dataField]:string.Empty) + ";";
				}
			}

			string result = "";

			foreach(string name in names)
			{
				result += String.Format("{0}={1};", name, Escape(nvCol[name]!=null?nvCol[name]:string.Empty));
			}

			return result;
		}

		public string BuildArguments(string path, object obj)
		{
			if(names == null || names.Count == 0)
			{
				if(path == null || path == string.Empty)
				{
					return string.Empty;
				}
				else
				{
					object value = ExpressionEvaluator.GetValue(obj, path);

					return path + "=" + Escape(value!=null?value.ToString():string.Empty) + ";";
				}
			}

			string result = "";

			foreach(string name in names)
			{
				object value = scopePathParser.Parse(obj, name).Value;
				result += String.Format("{0}={1};", name, Escape(value!=null?value.ToString():string.Empty));
			}

			return result;
			
		}

		public string BuildArguments(IDictionary executionContext)
		{
			if(contextNames == null || contextNames.Count == 0)
			{
				return string.Empty;
			}

			string result = "";
			for(IDictionaryEnumerator en = contextNames.GetEnumerator(); en.MoveNext();)
			{
				result += String.Format("{0}={1};", en.Value, Escape(executionContext[en.Key].ToString()));
			}
			return result;
		}

/*
		private string GetNameValuePairArgument(object name, object value)
		{
			string valueStr=value.ToString();
			if (escapeValues)
			{
				valueStr=HttpUtility.UrlEncode(valueStr);
			}	
			return String.Format("{0}={1}", name, valueStr);
		}
*/
/*
		public static NameValueCollection Parse(string commandArguments)
		{
			NameValueCollection name2value = new NameValueCollection();
			if (commandArguments==null||commandArguments.Trim().Equals(String.Empty))
			{
				return name2value;
			}
			string[] args =  commandArguments.Split(';');
			if(args == null || args.Length == 0)
			{
				return name2value;
			}
			foreach(string arg in args)
			{
				string[] nv = arg.Split('=');
				if(nv != null && nv.Length == 2)
				{
					name2value.Add(nv[0], HttpUtility.UrlDecode(nv[1]));
				}
			}
			return name2value;
		}
*/
		/// <summary>
		/// Behaves similar to javascript escape(). HttpUtility.UrlEncode() is not used because it doesn't
		/// accomplishes maximum encoding.
		/// </summary>
		/// <param name="str">String to be encoded</param>
		/// <returns>Encoded string</returns>
		private string Escape(string str)
		{
			if (!escapeValues)
			{
				return str;
			}
			StringBuilder builder=new StringBuilder(str.Length*2);
			foreach (char c in str)
			{
				if (Char.IsDigit(c)||(c>='a'&&c<='z')||(c>='A'&&c<='Z'))
				{
					builder.Append(c);
					continue;
				}
				string upper=((c&0xFF00)>>8).ToString("X");
				string lower=(c&0x00FF).ToString("X");
				builder.Append('%');
				if (!"0".Equals(upper))
				{
					builder.Append('u');
					if (upper.Length<2)
					{
						builder.Append('0');
					}
					builder.Append(upper);
				}
			
				if (lower.Length<2)
				{
					builder.Append('0');
				}
				builder.Append(lower);

			}
			return builder.ToString();
		}

	}
}
